/*
 * CopyLeft (c) 2001->infinity by Michael U. Bergens for starters.
 *
 *   Long story short: Apache 2.0, no warranty whatsoever, no obligations
 *   of any kind on the part of the authors nor on the part of the consumers of this code.
 */
package org.michael.u.brg.by.sys;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Executor for short programs/scripts that are expected to return reasonable number of content
 * in both out and err streams to fit in the memory.
 * @author Michael Bergens
 */
public class SysExecutorShort extends SysExecutor {

    private long maxMinutesToRun = Long.MAX_VALUE;

    @Override
    public ExecResultShort exec(String args[]) {
        final ExecResultShort result = new ExecResultShort();
        final List<Exception> errors = new LinkedList<Exception>();
        try {
            Process process = Runtime.getRuntime().exec(args);
            // todo how many does my core2 show: Runtime.getRuntime().availableProcessors();

            ListStreamConsumer outStreamConsumer = new ListStreamConsumer(process.getInputStream());
            ListStreamConsumer errStreamConsumer = new ListStreamConsumer(process.getErrorStream());

            ExecutorService execService = Executors.newFixedThreadPool(2);

            execService.submit(outStreamConsumer);
            execService.submit(errStreamConsumer);
            execService.shutdown();
            execService.awaitTermination(maxMinutesToRun, TimeUnit.MINUTES);

            process.waitFor();

            result.setExitCode(process.exitValue());
            result.setOutStream(outStreamConsumer.getContent());
            result.setErrStream(errStreamConsumer.getContent());
            errors.addAll(outStreamConsumer.getErrors());
            errors.addAll(errStreamConsumer.getErrors());
            result.setErrors(errors);
        }
        catch (Exception e) {
            errors.add(e);
            result.setErrors(errors);
            result.setExitCode(Integer.MIN_VALUE);
        }
        return result;
    }

    public long getMaxMinutesToRun() {
        return maxMinutesToRun;
    }

    public void setMaxMinutesToRun(long maxMinutesToRun) {
        this.maxMinutesToRun = maxMinutesToRun;
    }
}
